home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d8 / pdriver5.arc / NI5010.ASM < prev    next >
Assembly Source File  |  1989-12-17  |  19KB  |  763 lines

  1. version    equ    0
  2.  
  3.     include    defs.asm
  4.  
  5. ;Ported from Bill Doster's il.c, a C-language driver for the Interlan NI5010
  6. ;by Russell Nelson.  Any bugs are due to Russell Nelson.
  7. ;Updated to version 1.08 Feb. 17, 1989 by Russell Nelson.
  8.  
  9. ;   Copyright, 1988, 1989, Russell Nelson
  10.  
  11. ;   This program is free software; you can redistribute it and/or modify
  12. ;   it under the terms of the GNU General Public License as published by
  13. ;   the Free Software Foundation, version 1.
  14. ;
  15. ;   This program is distributed in the hope that it will be useful,
  16. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18. ;   GNU General Public License for more details.
  19. ;
  20. ;   You should have received a copy of the GNU General Public License
  21. ;   along with this program; if not, write to the Free Software
  22. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23.  
  24. code    segment    byte public
  25.     assume    cs:code, ds:code
  26.  
  27. ; The various IE command registers
  28. EDLC_XSTAT    equ    0        ; EDLC transmit csr
  29. EDLC_XCLR    equ    0        ; EDLC transmit "Clear IRQ"
  30. EDLC_XMASK    equ    1        ; EDLC transmit "IRQ Masks"
  31. EDLC_RSTAT    equ    2        ; EDLC receive csr
  32. EDLC_RCLR    equ    2        ; EDLC receive "Clear IRQ"
  33. EDLC_RMASK    equ    3        ; EDLC receive "IRQ Masks"
  34. EDLC_XMODE    equ    4        ; EDLC transmit Mode
  35. EDLC_RMODE    equ    5        ; EDLC receive Mode
  36. EDLC_RESET    equ    6        ; EDLC RESET register
  37. EDLC_TDR1    equ    7        ; "Time Domain Reflectometry" reg1
  38. EDLC_ADDR    equ    8        ; EDLC station address, 6 bytes
  39.                     ; 0Eh doesn't exist for r/w
  40. EDLC_TDR2    equ    0fh        ; "Time Domain Reflectometry" reg2
  41. IE_GP        equ    10h        ; GP pointer (word register)
  42.                     ; 11h is 2nd byte of GP Pointer
  43. IE_RCNT        equ    10h        ; Count of bytes in rcv'd packet
  44.                     ; 11h is 2nd byte of "Byte Count"
  45. IE_MMODE    equ    12h        ; Memory Mode register
  46. IE_DMA_RST    equ    13h        ; IE DMA Reset.  write only
  47. IE_ISTAT    equ    13h        ; IE Interrupt Status.  read only
  48. IE_RBUF        equ    14h        ; IE Receive Buffer port
  49. IE_XBUF        equ    15h        ; IE Transmit Buffer port
  50. IE_SAPROM    equ    16h        ; window on station addr prom
  51. IE_RESET    equ    17h        ; any write causes Board Reset
  52.  
  53. ; bits in EDLC_XSTAT, interrupt clear on write, status when read
  54. XS_TPOK        equ    80h        ; transmit packet successful
  55. XS_CS        equ    40h        ; carrier sense
  56. XS_RCVD        equ    20h        ; transmitted packet received
  57. XS_SHORT    equ    10h        ; transmission media is shorted
  58. XS_UFLW        equ    08h        ; underflow.  iff failed board
  59. XS_COLL        equ    04h        ; collision occurred
  60. XS_16COLL    equ    02h        ; 16th collision occurred
  61. XS_PERR        equ    01h        ; parity error
  62.  
  63. XS_CLR_UFLW    equ    08h        ; clear underflow
  64. XS_CLR_COLL    equ    04h        ; clear collision
  65. XS_CLR_16COLL    equ    02h        ; clear 16th collision
  66. XS_CLR_PERR    equ    01h        ; clear parity error
  67.  
  68. ; bits in EDLC_XMASK, mask/enable transmit interrupts.  register is r/w
  69. XM_TPOK        equ    80h        ; =1 to enable Xmt Pkt OK interrupts
  70. XM_RCVD        equ    20h        ; =1 to enable Xmt Pkt Rcvd ints
  71. XM_UFLW        equ    08h        ; =1 to enable Xmt Underflow ints
  72. XM_COLL        equ    04h        ; =1 to enable Xmt Collision ints
  73. XM_COLL16    equ    02h        ; =1 to enable Xmt 16th Coll ints
  74. XM_PERR        equ    01h        ; =1 to enable Xmt Parity Error ints
  75.                     ; note: always clear this bit
  76.  
  77. ; bits in EDLC_RSTAT, interrupt clear on write, status when read
  78. RS_PKT_OK    equ    80h        ; received good packet
  79. RS_RST_PKT    equ    10h        ; RESET packet received
  80. RS_RUNT        equ    08h        ; Runt Pkt rcvd.  Len < 64 Bytes
  81. RS_ALIGN    equ    04h        ; Alignment error. not 8 bit aligned
  82. RS_CRC_ERR    equ    02h        ; Bad CRC on rcvd pkt
  83. RS_OFLW        equ    01h        ; overflow for rcv FIFO
  84. RS_VALID_BITS    equ    RS_PKT_OK or RS_RST_PKT or RS_RUNT or RS_ALIGN or RS_CRC_ERR or RS_OFLW
  85.                     ; all valid RSTAT bits
  86.  
  87. RS_CLR_PKT_OK    equ    80h        ; clear rcvd packet interrupt
  88. RS_CLR_RST_PKT    equ    10h        ; clear RESET packet received
  89. RS_CLR_RUNT    equ    08h        ; clear Runt Pckt received
  90. RS_CLR_ALIGN    equ    04h        ; clear Alignment error
  91. RS_CLR_CRC_ERR    equ    02h        ; clear CRC error
  92. RS_CLR_OFLW    equ    01h        ; clear rcv FIFO Overflow
  93.  
  94. ; bits in EDLC_RMASK, mask/enable receive interrupts.  register is r/w
  95. RM_PKT_OK    equ    80h        ; =1 to enable rcvd good packet ints
  96. RM_RST_PKT    equ    10h        ; =1 to enable RESET packet ints
  97. RM_RUNT        equ    08h        ; =1 to enable Runt Pkt rcvd ints
  98. RM_ALIGN    equ    04h        ; =1 to enable Alignment error ints
  99. RM_CRC_ERR    equ    02h        ; =1 to enable Bad CRC error ints
  100. RM_OFLW        equ    01h        ; =1 to enable overflow error ints
  101.  
  102. ; bits in EDLC_RMODE, set Receive Packet mode.  register is r/w
  103. RMD_TEST    equ    80h        ; =1 for Chip testing.  normally 0
  104. RMD_ADD_SIZ    equ    10h        ; =1 5-byte addr match.  normally 0
  105. RMD_EN_RUNT    equ    08h        ; =1 enable runt rcv.  normally 0
  106. RMD_EN_RST    equ    04h        ; =1 to rcv RESET pkt.  normally 0
  107.  
  108. RMD_PROMISC    equ    03h        ; receive *all* packets.  unusual
  109. RMD_MULTICAST    equ    02h        ; receive multicasts too.  unusual
  110. RMD_BROADCAST    equ    01h        ; receive broadcasts & normal. usual
  111. RMD_NO_PACKETS    equ    00h        ; don't receive any packets. unusual
  112.  
  113. ; bits in EDLC_XMODE, set Transmit Packet mode.  register is r/w
  114. XMD_COLL_CNT    equ    0f0h        ; coll's since success.  read-only
  115. XMD_IG_PAR    equ    008h        ; =1 to ignore parity.  ALWAYS set
  116. XMD_T_MODE    equ    004h        ; =1 to power xcvr. ALWAYS set this
  117. XMD_LBC        equ    002h        ; =1 for loopbakc.  normally set
  118. XMD_DIS_C    equ    001h        ; =1 disables contention. normally 0
  119.  
  120. ; bits in EDLC_RESET, write only
  121. RS_RESET    equ    80h        ; =1 to hold EDLC in reset state
  122.  
  123. ; bits in IE_MMODE, write only
  124. MM_EN_DMA    equ    80h        ; =1 begin DMA xfer, Cplt clrs it
  125. MM_EN_RCV    equ    40h        ; =1 allows Pkt rcv.  clr'd by rcv
  126. MM_EN_XMT    equ    20h        ; =1 begin Xmt pkt.  Cplt clrs it
  127. MM_BUS_PAGE    equ    18h        ; =00 ALWAYS.  Used when MUX=1
  128. MM_NET_PAGE    equ    06h        ; =00 ALWAYS.  Used when MUX=0
  129. MM_MUX        equ    01h        ; =1 means Rcv Buff on system bus
  130.                     ; =0 means Xmt Buff on system bus
  131.  
  132. ; bits in IE_ISTAT, read only
  133. IS_TDIAG    equ    80h        ; =1 if Diagnostic problem
  134. IS_EN_RCV    equ    20h        ; =1 until frame is rcv'd cplt
  135. IS_EN_XMT    equ    10h        ; =1 until frame is xmt'd cplt
  136. IS_EN_DMA    equ    08h        ; =1 until DMA is cplt or aborted
  137. IS_DMA_INT    equ    04h        ; =0 iff DMA done interrupt. 
  138. IS_R_INT    equ    02h        ; =0 iff unmasked Rcv interrupt
  139. IS_X_INT    equ    01h        ; =0 iff unmasked Xmt interrupt
  140.  
  141. BFRSIZ        equ    2048    ;number of bytes in a buffer
  142.  
  143.     public    int_no
  144. int_no        db    3,0,0,0        ; interrupt number.
  145. io_addr        dw    0300h,0        ; I/O address for card (jumpers)
  146. ipkt_size    dw    ?
  147. opkt_size    dw    ?
  148.  
  149.     public    driver_class, driver_type, driver_name
  150. driver_class    db    1        ;from the packet spec
  151. driver_type    db    3        ;from the packet spec
  152. driver_name    db    'NI5010',0    ;name of the driver.
  153.  
  154.     public    rcv_modes
  155. rcv_modes    dw    4        ;number of receive modes in our table.
  156.         dw    0,0,0,rcv_mode_3
  157.  
  158. is_186        db    0        ;=0 if 808[68], =1 if 80[123]86.
  159. our_type    dw    ?
  160. intstat        db    ?
  161.  
  162.     public    send_pkt
  163. send_pkt:
  164. ;enter with ds:si -> packet, cx = packet length.
  165. ;exit with nc if ok, or else cy if error, dh set to error number.
  166.     assume    ds:nothing
  167.     cmp    cx,RUNT        ; minimum length for Ether
  168.     jae    oklen
  169.     mov    cx,RUNT        ; make sure size at least RUNT
  170. oklen:
  171.     inc    cx            ;round size up to next even number.
  172.     and    cx,not 1
  173.  
  174. ;Wait for transmitter ready, if necessary. IE_XMTBSY is valid
  175. ;only in the transmit mode, hence the initial check.
  176.  
  177.     loadport
  178.     setport    IE_ISTAT
  179.     in    al,dx
  180.     and    al,IS_EN_XMT        ;on-going xmit
  181.     je    send_pkt_2
  182.  
  183.     mov    bx,20000        ;try this many times.
  184. send_pkt_3:
  185.     in    al,dx            ;if not busy, exit.
  186.     and    al,IS_EN_XMT
  187.     je    send_pkt_2
  188.     dec    bx
  189.     jne    send_pkt_3
  190.     mov    dh,CANT_SEND        ;timed out, can't send.
  191.     stc
  192.     ret
  193. send_pkt_2:
  194.  
  195.     pushf            ; No distractions from the receiver
  196.     cli
  197.  
  198. ; Disable the Receiver
  199.     mov    al, 0        ; Mask all Receive Interrupts
  200.     loadport
  201.     setport    EDLC_RMASK
  202.     out    dx,al
  203.  
  204.     mov    al, 0        ; Put Xmt Buffer on System Bus
  205.     setport    IE_MMODE
  206.     out    dx,al
  207.  
  208.     mov    al, 0FFh    ; Clear out any pending Rcv Ints
  209.     setport    EDLC_RCLR
  210.     out    dx,al
  211.  
  212.     mov    ax, BFRSIZ    ; Point GP at beginning of packet
  213.     sub    ax,cx
  214.     setport    IE_GP
  215.     out    dx,ax
  216.  
  217.     setport    IE_XBUF
  218.  
  219.     mov    opkt_size,cx    ; opkt_size = cx;
  220.     cmp    is_186,0    ; Can we use rep outsb?
  221.     je    out86        ; no - have to do it slowly.
  222.     rep    outsb
  223.     jmp    short ocnteven
  224. out86:
  225.     test    si,1        ; (buf & 1) ?
  226.     jz    obufeven    ; no
  227.     lodsb            ; al = *si++;
  228.     out    dx,al        ; out(dx,al);
  229.     dec    cx        ; cx--;
  230. obufeven:
  231.     mov    di,cx        ; save for later test
  232.     shr    cx,1        ; cx = cnt >> 1; (convert to word count)
  233. ; Do the bulk of the buffer, a word at a time
  234.     jcxz    onobuf        ; if(cx != 0){
  235. xb:    lodsw            ; do { ax = *si++; (si is word pointer)
  236.     out    dx,al        ; out(dx,lowbyte(ax));
  237.     mov    al,ah
  238.     out    dx,al        ; out(dx,hibyte(ax));
  239.     loop    xb        ; } while(--cx != 0); }
  240. ; now check for odd trailing byte
  241. onobuf:    shr    di,1        ; if (di & 1)
  242.     jnc    ocnteven
  243.     lodsb            ;   out(dx,*si++);
  244.     out    dx,al
  245. ocnteven:
  246.  
  247. ; Rewrite where packet starts
  248.     mov    ax,BFRSIZ
  249.     sub    ax,opkt_size
  250.     loadport
  251.     setport    IE_GP
  252.     out    dx,ax
  253.  
  254. ; Flip Xmt Buffer to EDLC Bus so it can be transmitted
  255.     mov    al, MM_MUX
  256.     setport    IE_MMODE
  257.     out    dx,al
  258.  
  259. ; Begin transmission.
  260.     mov    al, MM_EN_XMT or MM_MUX
  261.     setport    IE_MMODE
  262.     out    dx,al
  263.  
  264. ; Cause interrupt after completion (or if something fails)
  265.     mov    al, XM_TPOK or XM_RCVD or XM_UFLW or XM_COLL or XM_COLL16
  266.     setport    EDLC_XMASK
  267.     out    dx,al
  268.  
  269.     popf
  270.     clc
  271.     ret
  272.  
  273.  
  274.     public    get_address
  275. get_address:
  276. ;get the address of the interface.
  277. ;enter with es:di -> place to get the address, cx = size of address buffer.
  278. ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
  279.     assume    ds:code
  280.     cmp    cx,EADDR_LEN            ;make sure that we have enough room.
  281.     jb    get_address_2
  282.     cmp    cx,9            ;do we have room for all of it?
  283.     jb    get_address_3        ;no.
  284.     mov    cx,9            ;yes - get the whole thing.
  285.     xor    bx,bx
  286.     jmp    short get_address_1
  287. get_address_3:
  288.     mov    cx,EADDR_LEN
  289.     xor    bx,bx
  290. get_address_1:
  291.     mov    ax,bx
  292.     loadport
  293.     setport    IE_GP
  294.     out    dx,ax
  295.  
  296.     setport    IE_SAPROM
  297.     in    al,dx
  298.     stosb
  299.     inc    bx
  300.     loop    get_address_1
  301.  
  302.     mov    cx,EADDR_LEN
  303.     clc
  304.     ret
  305. get_address_2:
  306.     stc
  307.     ret
  308.  
  309.  
  310. ;Set Ethernet address on controller
  311.     public    set_address
  312. set_address:
  313.     assume    ds:nothing
  314. ;enter with ds:si -> Ethernet address, CX = length of address.
  315. ;exit with nc if okay, or cy, dh=error if any errors.
  316. ;
  317.     cmp    cx,EADDR_LEN        ;ensure that their address is okay.
  318.     je    set_address_4
  319.     mov    dh,BAD_ADDRESS
  320.     stc
  321.     jmp    short set_address_done
  322. set_address_4:
  323.  
  324.     loadport
  325.     setport    EDLC_ADDR
  326. set_address_1:
  327.     lodsb
  328.     out    dx,al
  329.     inc    dx
  330.     loop    set_address_1
  331. set_address_okay:
  332.     mov    cx,EADDR_LEN        ;return their address length.
  333.     clc
  334. set_address_done:
  335.     push    cs
  336.     pop    ds
  337.     assume    ds:code
  338.     ret
  339.  
  340.  
  341. terminate:
  342.     ; put card in held-RESET state
  343.     mov    al,0
  344.     loadport
  345.     setport    IE_MMODE
  346.     out    dx,al
  347.     mov    al,RS_RESET
  348.     loadport
  349.     setport    EDLC_RESET
  350.     out    dx,al
  351.  
  352.     ret
  353.  
  354.  
  355. rcv_mode_3:
  356. ;receive mode 3 is the only one we support, so we don't have to do anything.
  357.     ret
  358.  
  359.  
  360.     public    set_multicast_list
  361. set_multicast_list:
  362. ;enter with es:di ->list of multicast addresses, cx = number of bytes.
  363. ;return nc if we set all of them, or cy,dh=error if we didn't.
  364.     mov    dh,NO_MULTICAST
  365.     stc
  366.     ret
  367.  
  368.  
  369.     public    get_multicast_list
  370. get_multicast_list:
  371. ;return with nc, es:di ->list of multicast addresses, cx = number of bytes.
  372. ;return cy, NO_ERROR if we don't remember all of the addresses ourselves.
  373. ;return cy, NO_MULTICAST if we don't implement multicast.
  374.     mov    dh,NO_MULTICAST
  375.     stc
  376.     ret
  377.  
  378.  
  379.     public    reset_interface
  380. reset_interface:
  381. ;reset the interface.
  382. ;we don't do anything.
  383.     ret
  384.  
  385.  
  386. ;called when we want to determine what to do with a received packet.
  387. ;enter with cx = packet length, es:di -> packet type.
  388.     extrn    recv_find: near
  389.  
  390. ;called after we have copied the packet into the buffer.
  391. ;enter with ds:si ->the packet, cx = length of the packet.
  392.     extrn    recv_copy: near
  393.  
  394.     extrn    count_in_err: near
  395.     extrn    count_out_err: near
  396.  
  397.     public    recv
  398. recv:
  399. ;called from the recv isr.  All registers have been saved, and ds=cs.
  400. ;Upon exit, the interrupt will be acknowledged.
  401.     assume    ds:code
  402.  
  403.     loadport
  404.     setport    IE_ISTAT
  405.     in    al,dx
  406.     mov    intstat,al
  407.  
  408. ; DMA Complete Interrupt.  We don't use DMA, but just in case ...
  409.     test    al,IS_DMA_INT
  410.     jne    recv_isr_3
  411.  
  412.     mov    al, 0         ; Reset DMA Interrupt
  413.     setport    IE_DMA_RST
  414.     out    dx,al
  415.  
  416. recv_isr_3:
  417.  
  418. ; Transmit Complete/Fail Interrupt
  419.     test    intstat,IS_X_INT
  420.     jne    recv_isr_1
  421.  
  422.     loadport
  423.     setport    EDLC_XSTAT
  424.     in    al,dx
  425.     mov    ah,al
  426.  
  427.     mov    al, 0            ; Disable Xmt IRQ's
  428.     setport    EDLC_XMASK
  429.     out    dx,al
  430.  
  431.     mov    al, 0FFh        ; clr all Xmt IRQ's
  432.     setport    EDLC_XCLR
  433.     out    dx,al
  434.  
  435.     test    ah,XS_COLL
  436.     je    recv_isr_1
  437.     ;Crank counter back to beginning and restart xmt
  438.  
  439.     mov    ax,BFRSIZ        ; Point GP at beginning of packet
  440.     sub    ax,opkt_size
  441.     setport    IE_GP
  442.     out    dx,ax
  443.  
  444.     mov    al, 0        ; De-assert MM_EN_RCV bit Just In Case
  445.     setport    IE_MMODE
  446.     out    dx,al
  447.  
  448.                 ; Flip Xmt Buffer to EDLC Bus and restart xmt
  449.     mov    al, MM_EN_XMT or MM_MUX
  450.     setport    IE_MMODE
  451.     out    dx,al
  452.  
  453.             ; Interrupt for all Transmit errors along with TPOK
  454.     mov    al, XM_TPOK or XM_RCVD or XM_UFLW or XM_COLL or XM_COLL16
  455.     setport    EDLC_XMASK
  456.     out    dx,al
  457.  
  458.     ret            ; Wait for it to complete again
  459.  
  460. recv_isr_1:
  461.     ; Is this a Receive Packet Interrupt?
  462.     test    intstat,IS_R_INT
  463.     jne    recv_isr_9_j_1        ;no.
  464.  
  465.     loadport
  466.     setport    EDLC_RSTAT        ;get the status of this packet
  467.     in    al,dx
  468.     and    al,RS_VALID_BITS
  469.     cmp    al,RS_PKT_OK        ;is it ok?
  470.     jne    recv_isr_7        ;yes.
  471.  
  472.     ; Clear the interrupt
  473.     mov    al, 0FFh
  474.     loadport
  475.     setport    EDLC_RCLR
  476.     out    dx,al
  477.  
  478.     ; Flip Rcv Buffer onto the system bus
  479.     mov    al, MM_MUX
  480.     setport    IE_MMODE
  481.     out    dx,al
  482.  
  483.     ; Get the size of the packet.
  484.     setport    IE_RCNT
  485.     in    ax,dx
  486.     mov    ipkt_size,ax
  487.  
  488.     cmp    ax,GIANT        ;greater than GIANT?
  489.     jbe    recv_isr_8        ;no.
  490. recv_isr_7:
  491.     call    count_in_err
  492. recv_isr_9_j_1:
  493.     jmp    recv_isr_9
  494. recv_isr_8:
  495. ;Put it on the receive queue
  496.  
  497.     mov    ax,EADDR_LEN+EADDR_LEN            ;seek to the type word.
  498.     setport    IE_GP
  499.     out    dx,ax
  500.  
  501.     setport    IE_RBUF
  502.     in    al,dx            ;read the type word out of the board.
  503.     mov    ah,al
  504.     in    al,dx
  505.     xchg    al,ah            ;should be in network byte order.
  506.     mov    our_type,ax
  507.  
  508.     mov    ax,ds            ;look up our type.
  509.     mov    es,ax
  510.     mov    di,offset our_type
  511.     mov    cx,ipkt_size
  512.     call    recv_find
  513.  
  514.     mov    ax,es            ;is this pointer null?
  515.     or    ax,di
  516.     je    recv_isr_9        ;yes - just free the frame.
  517.  
  518.     push    es            ;remember where the buffer pointer is.
  519.     push    di
  520.  
  521.     xor    ax,ax            ;seek to the beginning again.
  522.     loadport
  523.     setport    IE_GP
  524.     out    dx,ax
  525.  
  526.     mov    cx,ipkt_size
  527.     setport    IE_RBUF
  528.  
  529.     cmp    is_186,0    ; Can we use rep insb?
  530.     je    in86        ; no - have to do it slowly.
  531.     rep    insb
  532.     jmp    short icnteven
  533. in86:
  534. ; If buffer doesn't begin on a word boundary, get the first byte
  535.     test    di,1    ; if(buf & 1){
  536.     jz    ibufeven ;
  537.     in    al,dx    ; al = in(dx);
  538.     stosb        ; *di++ = al
  539.     dec    cx    ; cx--;
  540. ibufeven:
  541.     mov    si,cx    ; size = cx;
  542.     shr    cx,1    ; cx = cnt >> 1; (convert to word count)
  543. ; Do the bulk of the buffer, a word at a time
  544.     jcxz    inobuf    ; if(cx != 0){
  545. rb:    in    al,dx    ; do { al = in(dx);
  546.     mov    ah,al
  547.     in    al,dx    ; ah = in(dx);
  548.     xchg    al,ah
  549.     stosw        ; *si++ = ax; (di is word pointer)
  550.     loop    rb    ; } while(--cx != 0);
  551. ; now check for odd trailing byte
  552. inobuf:    shr    si,1
  553.     jnc    icnteven
  554.     in    al,dx
  555.     stosb        ; *di++ = al
  556. icnteven:
  557.  
  558.     pop    si
  559.     pop    ds
  560.     assume    ds:nothing
  561.     mov    cx,ipkt_size
  562.     call    recv_copy        ;tell them that we copied it.
  563.  
  564.     mov    ax,cs            ;restore our ds.
  565.     mov    ds,ax
  566.     assume    ds:code
  567.  
  568. recv_isr_9:
  569.  
  570. ; Prime Interlan card for another Receive
  571. il_rcv_reset:
  572.  
  573.     ; Rcv packet at start of Boards buffer
  574.     mov    ax,0
  575.     loadport
  576.     setport    IE_GP
  577.     out    dx,ax
  578.  
  579.     ; Clear any remaining Interrupt conditions
  580.     mov    al,0FFh
  581.     setport    EDLC_RCLR
  582.     out    dx,al
  583.  
  584.     ; Set MUX to allow EDLC to access Rcv Buffer
  585.     mov    al,0
  586.     setport    IE_MMODE
  587.     out    dx,al
  588.  
  589.     ; Enable Receive of Normal and Broadcast Packets only.
  590.     mov    al,RMD_BROADCAST
  591.     setport    EDLC_RMODE
  592.     out    dx,al
  593.  
  594.     ; Enable Receive Interrupts
  595.     mov    al,MM_EN_RCV
  596.     setport    IE_MMODE
  597.     out    dx,al
  598.  
  599.     ; Unmask *all* Receive related interrupts
  600.     mov    al,0FFh
  601.     setport    EDLC_RMASK
  602.     out    dx,al
  603.  
  604.     ret
  605.  
  606.  
  607.     public    recv_exiting
  608. recv_exiting:
  609. ;called from the recv isr after interrupts have been acknowledged.
  610. ;Only ds and ax have been saved.
  611.     assume    ds:nothing
  612.     ret
  613.  
  614.  
  615. end_resident    label    byte
  616.  
  617.     public    usage_msg
  618. usage_msg    db    "usage: NI5010 <packet_int_no> <int_no> <io_addr>",CR,LF,'$'
  619.  
  620.     public    copyright_msg
  621. copyright_msg    db    "Packet driver for the Interlan NI5010, version ",'0'+majver,".",'0'+version,CR,LF
  622.         db    "Portions Copyright 1988 Bill Doster",CR,LF,'$'
  623.  
  624.  
  625. using_186_msg    db    "Using 80[123]86 I/O instructions.",CR,LF,'$'
  626. no_ni5010_msg    db    "No NI5010 found at that address.",CR,LF,'$'
  627. ether_bdcst    db    EADDR_LEN dup(-1)    ;ethernet broadcast address.
  628. our_address    db    EADDR_LEN+3 dup(?)    ;temporarily hold our address
  629.  
  630. int_no_name    db    "Interrupt number ",'$'
  631. io_addr_name    db    "I/O port ",'$'
  632.  
  633.     extrn    set_recv_isr: near
  634.  
  635. ;enter with si -> argument string, di -> word to store.
  636. ;if there is no number, don't change the number.
  637.     extrn    get_number: near
  638.  
  639.     public    parse_args
  640. parse_args:
  641.     mov    di,offset int_no
  642.     mov    bx,offset int_no_name
  643.     call    get_number
  644.     mov    di,offset io_addr
  645.     mov    bx,offset io_addr_name
  646.     call    get_number
  647.     ret
  648.  
  649.  
  650. no_ni5010_error:
  651.     mov    dx,offset no_ni5010_msg
  652.     mov    ah,9
  653.     int    21h
  654.     stc
  655.     ret
  656.  
  657.  
  658.     public    etopen
  659. etopen:
  660. ;  Initialize the Ethernet board, set receive type.
  661. ;
  662. ;  check for correct EPROM location
  663. ;
  664.     pushf        ; No distractions from the receiver
  665.     cli
  666.  
  667.     ; Hold up EDLC RESET while the board is configured
  668.     mov    al,RS_RESET
  669.     loadport
  670.     setport    EDLC_RESET
  671.     out    dx,al
  672.  
  673.     ; Hardware reset of Interlan Board
  674.     mov    al,0
  675.     loadport
  676.     setport    IE_RESET
  677.     out    dx,al
  678.  
  679.     call    set_recv_isr
  680.  
  681.     popf        ; Shouldn't be any interrupts from here on out
  682.  
  683.     mov    al,XMD_LBC
  684.     loadport
  685.     setport    EDLC_XMODE
  686.     out    dx,al
  687.  
  688. ;Determine the processor type.  The 8088 and 8086 will actually shift ax
  689. ;over by 33 bits, while the 80[123]86 use a shift count mod 32.
  690.     mov    cl,33
  691.     mov    ax,0ffffh
  692.     shl    ax,cl
  693.     jz    not_186
  694.     mov    is_186,1
  695.     mov    dx,offset using_186_msg
  696.     mov    ah,9
  697.     int    21h
  698. not_186:
  699.  
  700.     push    ds
  701.     pop    es
  702.     mov    di,offset our_address
  703.     mov    cx,EADDR_LEN+3        ;get three extra signature bytes.
  704.     call    get_address
  705.     mov    si,offset our_address
  706.     mov    cx,EADDR_LEN
  707.     call    set_address
  708.  
  709. ;See if there really is a ni5010 there.
  710.     cmp    our_address+EADDR_LEN+0,0
  711.     jne    no_ni5010
  712.     cmp    our_address+EADDR_LEN+1,055h
  713.     jne    no_ni5010
  714.     cmp    our_address+EADDR_LEN+2,0aah
  715.     jne    no_ni5010
  716.  
  717.     mov    cx,EADDR_LEN
  718.     mov    di,offset ether_bdcst
  719.     repe    cmpsb
  720.     jne    have_ni5010        ;not broadcast address -- must be real.
  721. no_ni5010:
  722.     jmp    no_ni5010_error        ;not there -- no ni5010.
  723. have_ni5010:
  724.  
  725.     ; Only enable Transmit-type interrupts while Transmitting
  726.     mov    al,0
  727.     loadport
  728.     setport    EDLC_XMASK
  729.     out    dx,al
  730.  
  731.     ; Establish generic Transmit mode
  732.     mov    al,XMD_IG_PAR or XMD_T_MODE or XMD_LBC
  733.     setport    EDLC_XMODE
  734.     out    dx,al
  735.  
  736.     ; Clear any startup related Transmit interrupts
  737.     mov    al,0FFh
  738.     setport    EDLC_XCLR
  739.     out    dx,al
  740.  
  741.     ; Establish generic Receive mode
  742.     mov    al,RMD_BROADCAST
  743.     setport    EDLC_RMODE
  744.     out    dx,al
  745.  
  746.     ; Reset Rcv State to allow receives
  747.     call    il_rcv_reset
  748.  
  749.     ; Finally un-reset the EDLC
  750.     mov    al,0
  751.     loadport
  752.     setport    EDLC_RESET
  753.     out    dx,al
  754.  
  755.     mov    dx,offset end_resident
  756.     clc
  757.     ret
  758.  
  759.  
  760. code    ends
  761.  
  762.     end
  763.